﻿Option Explicit On
Option Strict On
Option Infer On
Imports System.IO
Imports System.Xml
Imports System.Linq
Imports System.Configuration

Namespace Configuration
    Public Module CfgManager
        Private Const XML_FILE_NAME As String = "Config.xml"
        Private WithEvents FSW As FileSystemWatcher
        Private XML As XmlDocument

        Private Sub LoadXML()
            XML = New XmlDocument()

            Dim strXml As String
            Try
                If Not File.Exists(Path.Combine(App_Data_Path, XML_FILE_NAME)) Then
                    Using sw As New StreamWriter(Path.Combine(App_Data_Path, XML_FILE_NAME))
                        sw.WriteLine("<?xml version=""1.0"" encoding=""utf-8"" ?>")
                        sw.WriteLine("<root>")
                        'sw.WriteLine("  <SqlPersistenceStoreConnection cnnType=""1""><![CDATA[Password=123;Persist Security Info=True;User ID=sa;Initial Catalog=BizuitPersistenceStoreSGC;Data Source=gold-movil-jb\sqlexpress]]>    ")
                        'sw.WriteLine("  </SqlPersistenceStoreConnection>")
                        'sw.WriteLine("  <SiteSqlServer cnnType=""1"">")
                        'sw.WriteLine("  <![CDATA[Password=123;Persist Security Info=True;User ID=sa;Initial Catalog=BizuitDashboard258;Data Source=gold-movil-jb\sqlexpress]]>    ")
                        'sw.WriteLine("  </SiteSqlServer>  ")
                        'sw.WriteLine("  <cnnType>1</cnnType>")
                        sw.WriteLine("  <logPath><![CDATA[" + IO.Path.Combine(App_Data_Path, "temp\path") + "]]></logPath>")
                        sw.WriteLine("  <logIsEnabled><![CDATA[True]]></logIsEnabled>")
                        sw.WriteLine("  <logCSVSplit><![CDATA[;]]></logCSVSplit>")
                        sw.WriteLine("  <logHeavy><![CDATA[False]]></logHeavy>")
                        sw.WriteLine("  <uploadpath><![CDATA[" + IO.Path.Combine(App_Data_Path, "uploadpath") + "]]></uploadpath>")
                        sw.WriteLine("  <uploadMenuAlloedExtensions><![CDATA[jpg,gif,ico,png]]></uploadMenuAlloedExtensions>")
                        sw.WriteLine("  <uploadMenuMaxKBSize><![CDATA[1024]]></uploadMenuMaxKBSize>")
                        sw.WriteLine("  <cryptokey><![CDATA[crrre]]></cryptokey>")
                        sw.WriteLine("  <baseURL><![CDATA[]]></baseURL>   ")
                        sw.WriteLine("</root>")
                        sw.Close()
                    End Using
                End If
                Using sr As New StreamReader(Path.Combine(App_Data_Path, XML_FILE_NAME))
                    strXml = sr.ReadToEnd()
                End Using
            Catch ex As Exception
                System.Threading.Thread.Sleep(500)
                Using sr As New StreamReader(Path.Combine(App_Data_Path, XML_FILE_NAME))
                    strXml = sr.ReadToEnd()
                End Using
            End Try

            If strXml Is Nothing Then
                Throw New ApplicationException("No se puede cargar el XML de configuración")
            End If
            XML.LoadXml(strXml)

        End Sub


        Public Function getAppSetting(Of T)(ByVal key As String) As T
            Try
                Dim ret As T = CType(CObj(System.Configuration.ConfigurationManager.AppSettings.Get(key)), T)
                Return ret
            Catch ex As Exception
                Return Nothing
            End Try
        End Function


        Private _RootPath As String = Nothing
        Public ReadOnly Property RootPath() As String
            Get
                If _RootPath Is Nothing Then
                    If Configuration.getAppSetting(Of String)("cfgrootpath") Is Nothing Then
                        If Web.HttpContext.Current IsNot Nothing _
                            AndAlso Web.HttpContext.Current.Server IsNot Nothing Then
                            _RootPath = Web.HttpContext.Current.Server.MapPath("~")
                        Else
                            _RootPath = My.Application.Info.DirectoryPath
                        End If
                    Else
                        _RootPath = Configuration.getAppSetting(Of String)("cfgrootpath")
                    End If

                End If
                Return _RootPath
            End Get
        End Property
        Public ReadOnly Property App_Data_Path() As String
            Get
                Dim app = IO.Path.Combine(RootPath, "App_Data")
                If Not IO.Directory.Exists(app) Then
                    Directory.CreateDirectory(app)
                End If
                Return app
            End Get
        End Property

        Public ReadOnly Property TempPath() As String
            Get
                Dim app = IO.Path.Combine(RootPath, IO.Path.Combine("App_Data", "Temp"))
                If Not IO.Directory.Exists(app) Then
                    Directory.CreateDirectory(app)
                End If
                Return app
            End Get
        End Property

        Public Function getConnectionString(ByVal cnnName As String) As System.Configuration.ConnectionStringSettings
            If ConfigurationManager.ConnectionStrings.Count > 0 Then
                Dim n = ConfigurationManager.ConnectionStrings.Item(cnnName)
                Return n
            End If
            Return Nothing
        End Function

        Public Function getNodeText(Of T)(ByVal nvalueName As String, Optional ByVal throwErrorIfNotExists As Boolean = False) As T
            Dim valueName = nvalueName
            If Not valueName.StartsWith("root") Then
                valueName = "root/" & valueName
            End If

            Dim val As T
            Dim nodo = XML.SelectSingleNode(valueName)

            If nodo Is Nothing Then
                If throwErrorIfNotExists Then
                    Throw New ApplicationException(String.Format("El nodo {0} no existe", valueName))
                Else
                    Dim result = getAppSetting(Of T)(nvalueName)
                    If result IsNot Nothing Then
                        Return result
                    Else
                        Try
                            If My.Settings.Properties.Count > 0 Then
                                Dim m = My.Settings.Item(nvalueName)
                            End If

                            If ConfigurationManager.ConnectionStrings.Count > 0 Then
                                Dim n = ConfigurationManager.ConnectionStrings.Item(nvalueName)
                                If n IsNot Nothing Then
                                    Return CType(CObj(n.ConnectionString), T)
                                End If

                            End If
                        Catch
                        End Try
                        Return Nothing
                    End If
                End If
            End If

            val = CType(CObj(nodo.InnerText.Trim()), T)
            Return val
        End Function

        Public Function getNodeAttribute(Of T)(ByVal sNodeName As String, ByVal attributeName As String, Optional ByVal throwErrorIfNotExists As Boolean = False) As T
            Dim nodeName As String = sNodeName
            If Not nodeName.StartsWith("root") Then
                nodeName = "root/" & nodeName
            End If

            Dim val As T
            Dim nodo = XML.SelectSingleNode(nodeName)

            If nodo Is Nothing Then
                If throwErrorIfNotExists Then
                    Throw New ApplicationException(String.Format("El nodo {0} no existe", nodeName))
                Else
                    Dim rs = getAppSetting(Of T)(sNodeName)
                    If rs IsNot Nothing Then
                        Return rs
                    Else
                        Try
                            If My.Settings.Properties.Count > 0 Then
                                Dim m = My.Settings.Item(attributeName)
                                If m IsNot Nothing Then
                                    Return CType(m, T)
                                End If
                            End If


                        Catch
                        End Try
                        Return Nothing
                    End If
                End If
            End If

            If nodo.Attributes Is Nothing OrElse nodo.Attributes.Count = 0 OrElse nodo.Attributes(attributeName) Is Nothing OrElse nodo.Attributes(attributeName).Value Is Nothing OrElse String.IsNullOrEmpty(nodo.Attributes(attributeName).Value.Trim()) Then
                If throwErrorIfNotExists Then
                    Throw New ApplicationException(String.Format("El attributo {0} no existe", attributeName))
                Else



                    Return Nothing
                End If
            End If

            val = CType(CObj(nodo.Attributes(attributeName).Value.Trim()), T)

            Return val

        End Function



        Private Sub FSW_Changed(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs)
            LoadXML()
        End Sub
        Public ReadOnly Property ExecutionPath() As String
            Get
                Return Path.Combine(RootPath, "bin")
            End Get
        End Property

        Public Function GetPickupDir() As System.Net.Configuration.SmtpSection
            Try
                Dim config = TryCast(System.Configuration.ConfigurationManager.GetSection("system.net/mailSettings/s‌​mtp"), System.Net.Configuration.SmtpSection)
                Return config
            Catch
                Return Nothing
            End Try

            ' Return If((config IsNot Nothing), config.SpecifiedPickupDirectory.PickupDirectoryLocation, Nothing)
        End Function

        Sub New()

            Try
                FSW = New FileSystemWatcher()
                With FSW
                    .Path = App_Data_Path
                    .Filter = XML_FILE_NAME
                    .IncludeSubdirectories = False
                    .NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)

                    AddHandler .Changed, AddressOf FSW_Changed
                    AddHandler .Created, AddressOf FSW_Changed
                    AddHandler .Deleted, AddressOf FSW_Changed
                    AddHandler .Renamed, AddressOf FSW_Changed

                    .EnableRaisingEvents = True
                End With

                LoadXML()
            Catch ex As Exception
                Throw (ex)
            End Try

        End Sub




    End Module
End Namespace
